package de.dhbw.minf12.mas.voter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import de.dhbw.minf12.mas.Permutation;
import de.dhbw.minf12.mas.logic.AbstractTargetFunctionLogic;
import de.dhbw.minf12.mas.util.PermutationTupleComparator;
import de.dhbw.minf12.mas.util.Tuple;

/**
 * Voter mit Approval Logik
 * @author flo
 *
 */
public class ApprovalVoter extends AbstractVoter{

	public ApprovalVoter(AbstractTargetFunctionLogic pTargetFunction) {
		super(pTargetFunction);
	}
	
	/**
	 * Voted nach dem Approval Verfahren.
	 * Bewertet alle Verträge und gibt alle zurück,
	 * die besser als der aktuelle Vertrag oder gleich gut sind
	 * (mindestens aber pMinApprovalCount).
	 * ACHTUNG: Kleine Werte sind besser als große (Ziel: niedrigste Zeit)
	 * @param pContracts zu bewertende Verträge
	 * @param pCurrentContract aktueller Vertrag
	 * @param pMinApprovalCount Mindestzahl zu wählender Verträge
	 * @return gewählte Verträge
	 */
	public List<Permutation> vote(List<Permutation> pContracts, Permutation pCurrentContract, int pMinApprovalCount){
		//Es sollte schon min 1 Vertrag zur Abstimmung kommen...
		if(pContracts.isEmpty()){
			return new LinkedList<Permutation>();
		}
		
		List<Tuple<Permutation, Integer>> scoredContracts = new ArrayList<Tuple<Permutation,Integer>>(pContracts.size());
		
		//Berechne die Qualität/Werte aller Verträge
		for(Permutation contract : pContracts){
			int solutionValue = this.targetFunction.calculateSolutionValue(contract);
			scoredContracts.add(new Tuple<Permutation, Integer>(contract, solutionValue));
		}
		
		//Sortiere die Liste von Verträgen absteigend nach Qualität/Wert/Score
		//niedrige Werte sind gut
		Collections.sort(scoredContracts, new PermutationTupleComparator());
		
		//Iteriere über die Liste der bewerteten Verträge und füge sie solange der Liste von gewählten Verträgen hinzu,
		//bis die Verträge schlechter sind als der aktuelle Vertrag und wir mindestens pMinApprovalCount Verträge gewählt haben.
		int valueOfCurrentContract = this.targetFunction.calculateSolutionValue(pCurrentContract);
		List<Permutation> votedContracts = new LinkedList<Permutation>();
		for(int i = 0;
				i < scoredContracts.size() && (i < pMinApprovalCount || scoredContracts.get(i).getSecondValue() <= valueOfCurrentContract);
				i++){
			votedContracts.add(scoredContracts.get(i).getFirstValue());
		}
		
		return votedContracts;
	}
}
